package com.sp.config;

import com.sp.filter.JwtAuthenticationTokenFilter;
import com.sp.intercepted.RequestAccessDeniedHandler;
import com.sp.intercepted.RequestAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * SpringSecurity配置，指定加/解密器
 *
 * @author tong
 */
@Configuration
@EnableWebSecurity
// 开启权限配置注解
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConfig {

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    private RequestAccessDeniedHandler requestAccessDeniedHandler;

    @Autowired
    private RequestAuthenticationEntryPoint requestAuthenticationEntryPoint;

    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        // 由于使用的是JWT，这里不需要csrf
        httpSecurity.csrf().disable()
                // 基于token，所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                // 允许对于网站静态资源的无授权访问
                .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/",
                        "/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js",
                        "/swagger-resources/**", "/v2/api-docs/**").permitAll()
                // 对登录注册要允许匿名访问（未登录允许访问，登录后不允许访问）
                .antMatchers("/employees/login", "/employees/checkCode", "/employees/refreshToken").permitAll()
                // 跨域请求会先进行一次options请求
                .antMatchers(HttpMethod.OPTIONS).permitAll()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated();

        // 禁用缓存
        httpSecurity.headers().cacheControl();

        // 添加jwtAuthenticationTokenFilter，到UsernamePasswordAuthenticationFilter之前
        httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        // 添加自定义未授权和未登录结果返回
        httpSecurity.exceptionHandling()
                .accessDeniedHandler(requestAccessDeniedHandler)
                .authenticationEntryPoint(requestAuthenticationEntryPoint);

        // 开启跨域访问
        httpSecurity.cors();

        return httpSecurity.build();
    }

    /**
     * 配置密码加密器
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}